#include <DefenseManager.h>
#include <BorderManager.h>
DefenseManager::DefenseManager(Arbitrator::Arbitrator<BWAPI::Unit*,double>* arbitrator)
{
	this->arbitrator = arbitrator;
}
void DefenseManager::setBorderManager(BorderManager* borderManager)
{
	this->borderManager = borderManager;
}
void DefenseManager::onOffer(std::set<BWAPI::Unit*> units)
{
	for(std::set<BWAPI::Unit*>::iterator u = units.begin(); u != units.end(); u++)
	{
		if (defenders.find(*u) == defenders.end())
		{
			arbitrator->accept(this, *u);
			defenders.insert(*u);
			getLeastDefended()->joinFormation(*u);
		}
	}
}

void DefenseManager::onRevoke(BWAPI::Unit* unit, double bid)
{
	if (CFormation* formation = CFormation::getFormation(unit))
		formation->leaveFormation(unit);
	defenders.erase(unit);
}

void DefenseManager::onRemoveUnit(BWAPI::Unit* unit)
{
	if (CFormation* formation = CFormation::getFormation(unit))
		formation->leaveFormation(unit);
	defenders.erase(unit);
}

void DefenseManager::update()
{
	// Bid on all completed military units
	std::set<BWAPI::Unit*> myPlayerUnits=BWAPI::Broodwar->self()->getUnits();
	for (std::set<BWAPI::Unit*>::iterator u = myPlayerUnits.begin(); u != myPlayerUnits.end(); u++)
	{
		if ((*u)->isCompleted() && 
			!(*u)->getType().isWorker() && 
			!(*u)->getType().isBuilding() &&
			(*u)->getType() != BWAPI::UnitTypes::Zerg_Egg &&
			(*u)->getType() != BWAPI::UnitTypes::Zerg_Larva)
		{
			arbitrator->setBid(this, *u, 20);
		}
	}
	bool borderUpdated = false;
	if (myBorder != borderManager->getMyBorder())
	{
		myBorder = borderManager->getMyBorder();
		borderUpdated = true;
	}
	int i=0;
	if (!myBorder.empty() && borderUpdated)
	{
		//Defend chokepoints
		for(std::set<CFormation*>::iterator j = formations.begin(); j != formations.end();j++)
		{
			(*j)->disbandFormation();
			(*j)->release();
		}
		formations.clear();
		for(std::set<BWTA::Chokepoint*>::iterator c = myBorder.begin(); c != myBorder.end(); c++)
		{
			CFormation* formation = CFormation::getEmptyFormation((*c)->getCenter(), ZFBlock);
			formation->reserve();
			formations.insert(formation);
		}
		//Put all unused units into formations
		for (std::set<BWAPI::Unit*>::iterator u = defenders.begin(); u != defenders.end(); u++)
		{
			CFormation* formation = getLeastDefended();
			formation->joinFormation(*u);
			//if ((*u).second.mode == DefenseData::Idle || borderUpdated)
			//{
			//	BWAPI::Position chokePosition=myBorderVector[i]->getCenter();
			//	i++;
			//	if (i>=(int)myBorderVector.size())
			//		i=0;
			//	(*u).first->attackMove(chokePosition);
			//	(*u).second.mode = DefenseData::Moving;
			//}
		}
	}
}

CFormation* DefenseManager::getLeastDefended()
{
	CFormation* smallest = 0;
	int size;
	for(std::set<CFormation*>::iterator j = formations.begin(); j != formations.end();j++)
	{
		if (smallest == 0 || (*j)->getUnits().size() < size)
		{
			smallest = (*j);
			size = (*j)->getUnits().size();
		}
	}
	return smallest;
}

std::string DefenseManager::getName() const
{
	return "Defense Manager";
}

std::string DefenseManager::getShortName() const
{
	return "Def";
}
